package structures.pane;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import manager.GrowlManager;

import domain.PaneNodeDAO;
import exception.IBToolsException;

public class XmlPane implements java.io.Serializable{
	
	private static final long serialVersionUID = 3956861426467538772L;
	
	private boolean inPane;
	
	private Map<Integer, XmlPaneNode> nodeListMap;
	private List<XmlPaneNode> nodeList;

	private int maximumIndex;
	private int selectedToUpdateIndex;
	private boolean selectedToUpdateTextChanged;

	private Integer sortStartIndex;
	private Integer sortStopIndex;
	
	public XmlPane(boolean inPane) {
		super();
		newNodeList();
		this.inPane = inPane;
		selectedToUpdateIndex = -1;
	}
	
	public List<XmlPaneNode> getNodeList() {
		if(nodeList == null)
			newNodeList();
		return nodeList;
	}
	
	private void newNodeList(){
		maximumIndex = 0;
		this.nodeList = new ArrayList<XmlPaneNode>(0);
		this.nodeListMap = new HashMap<Integer, XmlPaneNode>(0);
	}
	
	public void setNodeListManuel(List<PaneNodeDAO> nodes) throws IBToolsException {
		for (PaneNodeDAO paneNodeDAO : nodes) {
			maximumIndex = (nodeList.size() > maximumIndex ? nodeList.size() : maximumIndex);
			addNodeToPaneMap(new XmlPaneNode(this, paneNodeDAO, maximumIndex++));
		}
	}
	
	public void clear() throws IBToolsException{
		if(nodeList != null && nodeList.size() > 0){
			for (XmlPaneNode node : nodeList) {
				node.evict();
			}
			nodeList.clear();
			nodeListMap.clear();
			maximumIndex = 0;
			unSelectNodeToUpdate();
		}
	}
	public void unSelectNodeToUpdate(){
		selectedToUpdateIndex = -1;
		selectedToUpdateTextChanged = false;
	}
	public void selectNodeToUpdate(XmlPaneNode node) throws IBToolsException{
		selectedToUpdateIndex = node.getPaneIndex();
		selectedToUpdateTextChanged = false;
	}
	
	private void addNodeToPaneMap(XmlPaneNode node){
		getNodeList().add(node);
		nodeListMap.put(node.getPaneIndex(), node);
	}
	
	private void removeNodeFromPaneMap(XmlPaneNode node){
		getNodeList().remove(node);
		nodeListMap.remove(node.getPaneIndex());
	}
	public Integer putNodeToPane(String xmlString, long projectOid, String serviceName, String outXml, String xmlInfo, String source) throws IBToolsException{
		maximumIndex = (nodeList.size() > maximumIndex ? nodeList.size() : maximumIndex);
		XmlPaneNode node = new XmlPaneNode(this, xmlString, projectOid, serviceName, maximumIndex);
		node.setOutXml(outXml);
		node.setXmlInfo(xmlInfo);
		if(source != null)
			node.setNodeFromOtherSource(source);
		addNodeToPaneMap(node);
		selectedToUpdateIndex = maximumIndex;
		return maximumIndex++;
	}

	public void saveUnselectedNewNodeToDB(XmlPaneNode node) throws IBToolsException{
		node.setOrder(nodeList.size());
		node.activate(null, null, 0, null);
		reorganizeNodeOrders();
		selectedToUpdateTextChanged = false;
	}
	public void saveNewPaneNodeToDB(Integer paneIndex, String description) throws IBToolsException{
		nodeListMap.get(paneIndex).setOrder(nodeList.size());
		nodeListMap.get(paneIndex).activate(null, null, 0, description);
		reorganizeNodeOrders();
		selectedToUpdateTextChanged = false;
	}
	public void saveSelectedUpdatedNodeToDB(String xmlString, String serviceName, long projectOid, String nodeHeader) throws IBToolsException{
		nodeListMap.get(selectedToUpdateIndex).activate(xmlString, serviceName, projectOid, nodeHeader);
		selectedToUpdateTextChanged = false;
	}
	public boolean isNodeSelectedToUpdate(){
		return selectedToUpdateIndex > -1;
	}
	
	
	public void removeNodeFromPane(XmlPaneNode node) throws IBToolsException{
		if(node.getPaneIndex() == getSelectedToUpdateIndex())
			selectedToUpdateIndex = -1;
		node.evict();
		removeNodeFromPaneMap(node);
	}
	
	public void removeNodeFromDB(XmlPaneNode node) throws IBToolsException{
		if(node.getPaneIndex() == getSelectedToUpdateIndex())
			selectedToUpdateIndex = -1;
		node.delete();
		reorganizeNodeOrders();
	}

	public int getSelectedToUpdateIndex() {
		return selectedToUpdateIndex;
	}
	
	public XmlPaneNode getSelectedToUpdateNode() {
		return nodeListMap.get(selectedToUpdateIndex);
	}

	public boolean isInPane() {
		return inPane;
	}

	public boolean isSelectedToUpdateTextChanged() {
		return selectedToUpdateTextChanged;
	}

	public void setSelectedToUpdateTextChanged(boolean selectedToUpdateTextChanged) {
		this.selectedToUpdateTextChanged = selectedToUpdateTextChanged;
	}
	public void changeSelectedText(){
		selectedToUpdateTextChanged = true;
	}
	
	public void moveNodePrevious() throws IBToolsException{
		if(isNodeSelectedToUpdate()){
			XmlPaneNode node = nodeListMap.get(selectedToUpdateIndex);
			int nodeIndex = nodeList.indexOf(node);
			int prevNodeIndex = nodeIndex - 1;
			
			if(prevNodeIndex < 0)
				prevNodeIndex = nodeList.size() - 1;
			XmlPaneNode prevNode = nodeList.get(prevNodeIndex);
			
			if(node.isPersisted() && prevNode.isPersisted()){
				Integer prevNodeOrder = prevNode.getPaneOrder();
				prevNode.setOrder(node.getPaneOrder());
				prevNode.activate(null, null, 0, null);
				node.setOrder(prevNodeOrder);
				node.activate(null, null, 0, null);
			}
			
			nodeList.set(nodeIndex, prevNode);
			nodeList.set(prevNodeIndex, node);
		}
	}
	
	public void moveNodeNext() throws IBToolsException{
		if(isNodeSelectedToUpdate()){
			XmlPaneNode node = nodeListMap.get(selectedToUpdateIndex);
			int nodeIndex = nodeList.indexOf(node);
			int nextNodeIndex = nodeIndex + 1;
			
			if(nextNodeIndex >= nodeList.size())
				nextNodeIndex = 0;
			XmlPaneNode nextNode = nodeList.get(nextNodeIndex);

			if(node.isPersisted() && nextNode.isPersisted()){
				Integer nextNodeOrder = nextNode.getPaneOrder();
				nextNode.setOrder(node.getPaneOrder());
				nextNode.activate(null, null, 0, null);
				node.setOrder(nextNodeOrder);
				node.activate(null, null, 0, null);
			}

			nodeList.set(nodeIndex, nextNode);
			nodeList.set(nextNodeIndex, node);
		}
	}
	public void reorganizeNodeOrders() throws IBToolsException{
		int i = 0;
		for (XmlPaneNode xmlPaneNode : nodeList) {
			if(xmlPaneNode.isPersisted()){
				xmlPaneNode.setOrder(i);
				xmlPaneNode.activate(null, null, 0, null);
				i++;
			}
		}
	}
	public void sort(long selectedProjectOid) throws IBToolsException{
		if(sortStartIndex == sortStopIndex)
			return;
		if(selectedProjectOid < 0){
			GrowlManager.addWarning("Re-order Pane Node", "Select Project");
			return;
		}
		XmlPaneNode startNode = nodeList.get(sortStartIndex);
		nodeList.remove(sortStartIndex.intValue());
		nodeList.add(sortStopIndex, startNode);
		if(startNode.isPersisted())
			reorganizeNodeOrders();
	}

	public Integer getSortStartIndex() {
		return sortStartIndex;
	}

	public void setSortStartIndex(Integer sortStartIndex) {
		this.sortStartIndex = sortStartIndex;
	}

	public Integer getSortStopIndex() {
		return sortStopIndex;
	}

	public void setSortStopIndex(Integer sortStopIndex) {
		this.sortStopIndex = sortStopIndex;
	}
	
}
